/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package teste;

import config.LogErro;
import controllers.AtributoAuxController;
import controllers.AtributoDimController;
import controllers.DimensaoController;
import controllers.JdbcAuxController;
import controllers.JdbcDimController;
import controllers.TabAuxController;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.HashMap;
import models.entidades.Dimensao;
import models.entidades.Procedimento;
import models.entidades.TabAux;
import teste.utilitario.ManipulaHash;

/**
 *
 * @author Wenderson
 */
public class Testes {
    
    private Procedimento p;
    
    private HashMap<String, String> atrAux;
    private HashMap<String, String> chavesRef;
    private HashMap<String, String> atrNaoChave;
    private HashMap<String, String> atrRef;
    
    private HashMap<String, ArrayList<Object>> inserts;
    
    private ArrayList<String> listErros;
    
    public Testes(Procedimento p) {
        this.p = p;
        
        listErros = new ArrayList<String>();
    }
    
    //<editor-fold defaultstate="collapsed" desc="Get Atributos">
    private HashMap<String, String> getAtributosAux() {
        if (this.atrAux == null || this.atrAux.size() <= 0) {
            this.atrAux = AtributoAuxController.getNomeTipo(this.p);
        }
        return atrAux;
    }
    
    private HashMap<String, String> getChavesReferenciadas() {
        if (this.chavesRef == null || this.chavesRef.size() <= 0) {
            this.chavesRef = AtributoAuxController.getChavesReferenciadas(this.p);
        }
        // System.out.println("CHAVES REFERENCIADAS: " + chavesRef.toString());
        return chavesRef;
    }
    
    private HashMap<String, String> getAtributosReferenciados() {
        if (this.atrRef == null || this.atrRef.size() <= 0) {
            this.atrRef = AtributoAuxController.getAtributosReferenciados(this.p);
        }
        return atrRef;
    }
    
    private HashMap<String, String> getAtributosNaoChaves(int tipo_atributo) {
        if (this.atrNaoChave == null || this.atrNaoChave.size() <= 0) {
            this.atrNaoChave = AtributoAuxController.getAtributosNaoChaves(this.p, tipo_atributo);
        }
        return atrNaoChave;
    }
    //</editor-fold>
    
    public boolean teste1A() {
        try {
            TabAux tabAux = p.getTabAux();
            Dimensao dimensao = p.getDimensao();
            
            int countAux = JdbcAuxController.count(tabAux.getEsquema(), tabAux.getNome());
            int countDim = JdbcDimController.count(dimensao.getEsquema(), dimensao.getNome());
            
            if (countAux == countDim) {
                return true;
            } else {
                String erro = String.format("TESTE 1 ERRO: Quantidade Tab Auxiliar (%d) diferente da Dimensão (%d)", 
                        countAux, countDim);
                
                listErros.add(erro);
            }
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        
        return false;
    }
    
    public boolean teste1B() {
        try {
            chavesRef = getChavesReferenciadas();
            
            ResultSet rs = JdbcAuxController.getResultadoChave(this.p.getTabAux(), chavesRef);
            
            boolean resultado = false;

            if (rs == null) {
                return false;
            }
            
            while (rs.next()) {
                int count = JdbcDimController.resultadoValorChaves(p.getDimensao(), chavesRef, rs);
                
                if (count != 1) {
                    String erro = String.format("TESTE 2 ERRO: Quantidade Registros Por Chave (%d) esperado (%d).", 
                        count, 1);
                
                    listErros.add(erro);
                    
                    return false;
                }
                
                resultado = true;
            }
            
            rs.close();
            
            return resultado;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste1C() {
        try {
            atrRef = getAtributosReferenciados();
            
            ResultSet rs = JdbcAuxController.getResultadoChave(this.p.getTabAux(), atrRef);
            
            boolean resultado = false;
            
            if (rs == null) {
                return false;
            }
            
            while (rs.next()) {
                int count = JdbcDimController.resultadoValorChaves(this.p.getDimensao(), atrRef, rs);
                
                if (count != 1) {
                    String erro = String.format("TESTE 3 ERRO: Quantidade Valor de Coluna por Chave (%d) esperado (%d).",
                        count, 1);
                
                    listErros.add(erro);
                
                    return false;
                }
                
                resultado = true;
            }
            
            rs.close();
            
            return resultado;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste2() {
        try {
            boolean resultado = this.teste1A();
            
            if (resultado) {
                return resultado;
            }
            
            String erro = String.format("TESTE 4 ERRO: Quantidade de registros da Tab Auxiliar e Dimensão são diferentes");
                
            listErros.add(erro);
            
            return false;            
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste3A() {
        try {
            chavesRef = getChavesReferenciadas();
            atrNaoChave = getAtributosNaoChaves(1);
            
            ResultSet rsChave = JdbcAuxController.getResultadoChave(this.p.getTabAux(), chavesRef);
            ResultSet rsAtrib = JdbcAuxController.getResultadoChave(this.p.getTabAux(), atrNaoChave);
            
            if (rsChave == null || rsAtrib == null) {
                return false;
            }
            
            rsChave.first();
            rsAtrib.first();
            
            ArrayList<String> nomeAtr = ManipulaHash.list(atrNaoChave, false);
            
            int countColuna = rsAtrib.getMetaData().getColumnCount();
            
            int indice = 1;
            
            while (indice <= countColuna) {
                do {
                    int count = JdbcDimController.resultadoValorChaveAtributo(this.p.getDimensao(), chavesRef, rsChave, nomeAtr.get(indice - 1), rsAtrib.getObject(indice));
                    
                    if (count != 1) {
                        rsChave.close();
                        rsAtrib.close();
                        
                        String erro = String.format("TESTE 5 ERRO: Valor da Coluna (%s) após alteração está incorreto na dimensão.",
                                        nomeAtr.get(indice - 1));
                
                        listErros.add(erro);
                        
                        return false;
                    }
                    
                    rsChave.next();
                } while (rsAtrib.next());
                
                rsAtrib.first();
                rsChave.first();
                indice++;
            }
            
            rsChave.close();
            rsAtrib.close();
            
            return true;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste3B(int quantidadeAtual) {
        try {
            int countDim = JdbcDimController.count(this.p.getDimensao().getEsquema(), this.p.getDimensao().getNome());
            
            if (countDim != quantidadeAtual) {
                String erro = String.format("TESTE 6 ERRO: Quantidade de registros na Dimensão antes (%d) e após (%d) alteração de um "
                        + "Atributo não corresponde.",
                                        quantidadeAtual, countDim);
                
                listErros.add(erro);
                
                return false;
            }
            
            return true;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste4A() {
        try {
            chavesRef = getChavesReferenciadas();
            ResultSet rsChave = JdbcAuxController.getResultadoChave(this.p.getTabAux(), chavesRef);
            
            boolean resultado = false;
            
            if (rsChave == null) {
                return false;
            }
            
            while (rsChave.next()) {
                int count = JdbcDimController.resultadoValorChaves(this.p.getDimensao(), chavesRef, rsChave);
                
                if (count != 2) {
                    rsChave.close();
                    
                    String erro = String.format("TESTE 7 ERRO: Quantidade de registros por chave natural "
                            + "após alteração de tipo 2 não corresponde. Encontrado (%d), esperado (%d) numa chave.",
                            count, 2);
                
                    listErros.add(erro);
                    
                    return false;
                } else {
                    resultado = true;
                }
            }

            rsChave.close();
            
            return resultado;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste4B(int quantidadeAtual) {
        try {
            int count = JdbcDimController.count(this.p.getDimensao().getEsquema(), this.p.getDimensao().getNome());
            
            if (count != quantidadeAtual) {
                String erro = String.format("TESTE 8 ERRO: Quantidade de registros por chave natural "
                            + "após alteração de tipo 2 não corresponde. Encontrado (%d), esperado (%d).",
                            quantidadeAtual, count);
                
                listErros.add(erro);
                
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        
        return false;
    }
    
    public boolean teste4C() {
        try {
            String nomeDataFinal = AtributoDimController.getNomeDataFinal(this.p);
            String nomeFlag = AtributoDimController.getNomeFlCorrente(this.p);
            
            chavesRef = getChavesReferenciadas();
            ResultSet rsAux = JdbcAuxController.getResultadoChave(this.p.getTabAux(), chavesRef);
            
            boolean resultado = false;
            
            if (rsAux == null) {
                return false;
            }
            
            while (rsAux.next()) {
                int count = JdbcDimController.getDataFlCorrente(this.p.getDimensao(), chavesRef, rsAux, nomeDataFinal, nomeFlag, "N");
                
                if (count != 1) {
                    rsAux.close();
                    
                    String erro = String.format("TESTE 9 ERRO: Valor de Fl Corrente (%s) e Data Final (%s) está (ão) incorreto(s).",
                            nomeFlag, nomeDataFinal);
                
                    listErros.add(erro);
                    
                    return false;
                } else {
                    resultado = true;
                }
            }
            
            rsAux.close();
            
            return resultado;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste4D() {
        try {
            String nomeDataInicial = AtributoDimController.getDataInicial(this.p);
            String nomeFlCorrente = AtributoDimController.getNomeFlCorrente(this.p);
            
            chavesRef = getChavesReferenciadas();
            
            ResultSet rsAux = JdbcAuxController.getResultadoChave(this.p.getTabAux(), chavesRef);
            
            boolean resultado = false;
            
            if (rsAux == null) {
                return false;
            }
            
            while (rsAux.next()) {
                int count = JdbcDimController.getDataFlCorrente(this.p.getDimensao(), chavesRef, rsAux, nomeDataInicial, nomeFlCorrente, "S");
                
                if (count != 1) {
                    rsAux.close();
                    
                    String erro = String.format("TESTE 10 ERRO: Valor de Fl Corrente (%s) e Data Inicial (%s) está (ão) incorreto(s).",
                            nomeFlCorrente, nomeDataInicial);
                
                    listErros.add(erro);
                    
                    return false;
                } else {
                    resultado = true;
                }
            }
            
            rsAux.close();
            
            return resultado;
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste4E(HashMap<String, ArrayList<Object>> lista, int quantidade) {
        try {
            int countAntes = JdbcDimController.count(this.p.getDimensao().getEsquema(), this.p.getDimensao().getNome());
            
            ManipulaBanco.executarProcedimento(this.p);
            
            int countDepois = JdbcDimController.count(this.p.getDimensao().getEsquema(), this.p.getDimensao().getNome());
            
            if (countAntes != countDepois) {
                String erro = String.format("TESTE 11 ERRO: Quantidade de registros incorreta após alteração de Atributos"
                        + " que podem receber valores (null). Antes (%d) e Depois (%d) da alterção",
                            countAntes, countDepois);
                
                listErros.add(erro);
                
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste4F(HashMap<String, ArrayList<Object>> lista, int quantidade) {
        try {
            int countAntes = JdbcDimController.count(this.p.getDimensao().getEsquema(), this.p.getDimensao().getNome());
            
            ManipulaBanco.inserirDados(this.p, lista, quantidade);
            ManipulaBanco.executarProcedimento(this.p);
            
            int countDepois = JdbcDimController.count(this.p.getDimensao().getEsquema(), this.p.getDimensao().getNome());
            
            if (countAntes != countDepois) {
                String erro = String.format("TESTE 12 ERRO: Quantidade de registros incorreta após alteração de Atributos"
                        + " do tipo (char, varchar) de Letras Minúsculas para Maiúsculas. Antes (%d) e Depois (%d) da alterção",
                            countAntes, countDepois);
                
                listErros.add(erro);
                
                return false;
            } else {
                return true;
            }
            
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public boolean teste5() {
        try {
            chavesRef = getChavesReferenciadas();
            atrNaoChave = getAtributosNaoChaves(1);
            
            ResultSet rsChaves = JdbcAuxController.getResultadoChave(this.p.getTabAux(), chavesRef);
            ResultSet rsAtributos = JdbcAuxController.getResultadoChave(this.p.getTabAux(), atrNaoChave);
            
            if (rsChaves == null || rsAtributos == null) {
                return false;
            }
            
            rsChaves.first();
            rsAtributos.first();
            
            ArrayList<String> nomeAtributo = new ArrayList<String>();
            
            for (String atributo : atrNaoChave.keySet()) {
                nomeAtributo.add(atrNaoChave.get(atributo));
            }
            
            int countColuna = rsAtributos.getMetaData().getColumnCount();
            
            int indice = 1;
            
            while (indice <= countColuna) {
                do {
                    int count = AtributoDimController.resultadoValorChaveAtributo(this.p, chavesRef, rsChaves, nomeAtributo.get(indice - 1), rsAtributos.getObject(indice));
                    
                    if (count != 2) {
                        rsChaves.close();
                        rsAtributos.close();
                        
                        String erro = String.format("TESTE 13 ERRO: Quantidade de registros por chave natural "
                            + "após alteração de tipo 2 não corresponde. Encontrado (%d), esperado (%d) numa chave.",
                            count, 2);
                
                        listErros.add(erro);
                        
                        return false;
                    }
                    
                    rsChaves.next();
                } while (rsAtributos.next());
                
                rsAtributos.first();
                rsChaves.first();
                indice++;
            }
            
            rsChaves.close();
            rsAtributos.close();
            
            if (this.teste4A()) {
                return true;
            } else {
                String erro = String.format("TESTE 13 ERRO: Quantidade de registros da Tab Auxiliar e Dimensão são diferentes");

                listErros.add(erro);
                return false;
            }
        } catch (Exception e) {
            LogErro.gravaErro(e);e.printStackTrace();
        }
        return false;
    }
    
    public ArrayList<String> listaErros() {
        return listErros;
    }
}
